﻿/*******************************************************************
Copyright (c) 2011 이재범

*  Permission is hereby granted, free of charge, to any person
*  obtaining a copy of this software and associated documentation
*  files (the "Software"), to deal in the Software without
*  restriction, including without limitation the rights to use,
*  copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the
*  Software is furnished to do so, subject to the following
*  conditions:
* 
*  The above copyright notice and this permission notice shall be
*  included in all copies or substantial portions of the Software.
* 
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*  OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************/

#include "equation.h"
#include "exception.h"

void remove_braket_parenth(string &str)
{
	if(str.empty())
		return;

	string::iterator itr = str.end() - 1;
	while (true)
	{
		if(*itr == ' ')
		{
			str.erase(itr);
			if(str.length() == 0)
				break;

			itr --;
			continue;
		}
		else
			break;
	}

	itr = str.begin();
	while (itr != str.end())
	{
		if(*itr == '{' || *itr == '}' || *itr == '(' || *itr == ')' || *itr == '\\')
		{
			str.erase(itr);
			continue;
		}
		else if(*itr == ' ')
		{
			str.replace(itr, itr + 1, "@");
			continue;
		}
		itr ++;
	}
}

void Equation::natural_language_process()
{
	if(equation.empty())
	{
		is_normalized = false;
		return;
	}

	for(int i = 0; i < equation.size(); i ++)
	{
		if(static_cast<unsigned char>(equation[i]) <= 31)
		{
			equation.erase(equation.begin() + i);
			i --;
		}
	}

	adjust_latex();
	if(!is_normalized)
		return;

	while (!equation.empty())
	{
		// 수식 끝이 ' ' 이면
		if (!equation.empty() && *(equation.end() - 1) == ' ')
		{
			equation.erase(equation.end() - 1, equation.end());
		}
		// 수식 끝이 마침표로 끝나면
		else if(!equation.empty() && *(equation.end() - 1) == '.')
		{
			equation.erase(equation.end() - 1, equation.end());
		}

		// 수식 끝이 쉼표로 끝나면
		else if(!equation.empty() && *(equation.end() - 1) == ',')
		{
			equation.erase(equation.end() - 1, equation.end());
		}
		else
			break;
	}

	is_syntax_correct();
	if(!is_normalized)
		return;

	enclose_numbers();

	adjust_braket();
	if(!is_normalized)
		return;

	adjust_operators();
	if(!is_normalized)
		return;

	adjust_dots();

	if(equation.empty())
		is_normalized = false;

	if(!is_normalized)
		return;

	adjust_subscript();
	if(!is_normalized)
		return;

	string operator_name;
	for(int i = 0; i < static_cast<int>(equation.size()); i ++)
	{
		if(equation[i] == '\\')
		{
			get_symbol_name(i, operator_name);
			if(operator_name.empty())
			{
				is_normalized = false;
				return;
			}
		}
	}

}
void Equation::adjust_operators()
{
	string::size_type location;
	string operator_name;

	if(operator_change_from.size() != operator_change_to.size())
		throw Error::general_error(2);

	for(int i = 0; i < operator_change_from.size(); i ++)
	{
		location = equation.find(operator_change_from[i]);
		while (location != string::npos)
		{
			equation.replace(location, operator_change_from[i].length()," " + operator_change_to[i] + " ");
			location = equation.find(operator_change_from[i]);
		}
	}

	// \frac{}{} 을 {} \frac {} 으로 수정 
	for(location = 0; location < equation.length(); location++)
	{
		if(equation[location] == '\\')
		{
			get_symbol_name(location, operator_name);
			if(operator_name == "frac")
			{
				equation.replace(location, 5, ""); // 그 부분의 \frac 을 지우고
				string::size_type find = location; // \frac 이 지워졌으므로 그 부분에는 \frac 바로 다음이 온다.
				int count = 0;
				for(;find <= equation.length(); find++)
				{
					if(equation[find] == '{' || equation[find] == '(')
						count ++;
					else if(equation[find] == '}' || equation[find] == ')')
						count --;
					else if(equation[find] == ' ')
						continue;

					if(count == 0) // 맨 처음에 무조건 { 를 만나게 되있다. 
					{
						// insert 는 가리키는 것 앞에 넣는다. 
						equation.insert(find + 1, "\\fraac"); // 무엇이 바뀌었는지 표시하기 위해 \fraac 으로 넣고 나중에 다시 바꿈
						break;
					}
				}
				location = location + operator_name.length();
			}
		}
	}

	location = equation.find("\\fraac");
	while (location != string::npos)
	{
		equation.replace(location, 6, " \\times \\frac ");
		location = equation.find("\\fraac");
	}

	// tilde 처리
	location = equation.find("\\~");
	while (location != string::npos)
	{
		int original_loc = location;
		location += 2;
		equation.insert(location, "{");
		location ++;

		while (location < equation.size())
		{
			if(equation[location] == ' ')
				continue;
			else
			{
				equation.insert(location + 1, "}");
				break;
			}
			location ++;
		}

		equation.replace(original_loc, 2, "\\tilde_");
		location = equation.find("\\~");
	}

	location = equation.find("~");
	while (location != string::npos)
	{
		equation.replace(location, 1, " ");
		location = equation.find("~");
	}

	// 예컨대 ax + b 의 경우 + 가 덧셈 기호로 사용되었지만
	// S_{+} b 의 경우 + 가 단순한 기호로 사용된 것이다. 
	// 일단은 +, *, - 이 세 개의 기호들의 대해서만 생각해보기로 하자.

	for(int i = 0; i < operator_as_symbol_list.size(); i++)
	{
		location = equation.find("\\" + operator_as_symbol_list[i]);
		bool is_possible_for_symbol = false;
		bool is_possible_for_subscript = false;
		while (location != string::npos)
		{
			int find = location - 1;
			bool isoperator = false;
			for(;find >= 0;find --)
			{
				// + 왼쪽에 붙어있는 것이 연산자가 아니였다면
				if(equation[find] == ' ' && isoperator)
					break;

				if(equation[find] == ' ')
					continue;

				if(is_alpha(equation[find]))
				{
					isoperator = true;
					continue;
				}

				if(equation[find] == '{' || equation[find] == '(')
				{
					if(!isoperator)
					{
						is_possible_for_symbol = true;
						break;
					}
					else
						break;
				}

				if(equation[find] == '}' || equation[find] == ')')
					break;

				// 만일 앞에 붙어 있는 것이 연산자였다면
				if(equation[find] == '\\')
				{
					if(is_operator(find, operator_name))
					{
						// 이항 연산자라면
						if(is_two_parameter_operator(operator_name) || operator_name == "minus")
						{
							is_possible_for_symbol = true;
							break;
						}
					}
					else
					{
						break;
					}
				}
				else if(equation[find] == '_' || equation[find] == '^')
				{
					is_possible_for_symbol = true;
					is_possible_for_subscript = true;
					break;
				}
				else
					break;
			}
			if(is_possible_for_symbol)
			{
				int find = location + operator_as_symbol_list[i].length() + 1;
				for (;find < static_cast<int>(equation.length()); find ++)
				{
					if(equation[find] == '\\')
					{
						if(is_operator(find, operator_name))
						{
							// 이항 연산자라면
							if(is_two_parameter_operator(operator_name) || operator_name == "minus")
							{
								equation.replace(location, operator_as_symbol_list[i].length() + 1, "\\symbol"+operator_as_symbol_list[i]);
								break;
							}
							else
								break;
						}
						else
							break;
					}
					if(equation[find] == '}' || equation[find] == ')')
					{
						equation.replace(location, operator_as_symbol_list[i].length() + 1, "\\symbol"+operator_as_symbol_list[i]);
						break;	
					}
					if((equation[find] == '{' || equation[find] == '(') && !is_possible_for_subscript)
						break;
					else if((equation[find] == '{' || equation[find] == '(') && is_possible_for_subscript)
					{
						equation.replace(location, operator_as_symbol_list[i].length() + 1, "\\symbol"+operator_as_symbol_list[i]);
						break;
					}
					if(equation[find] == ' ')
						continue;
					else
						break;
				}
			}
			location = equation.find("\\" + operator_as_symbol_list[i], location + 1);
		}
	}

	location = equation.find("\\minus");
	while (location != string::npos)
	{
		equation.replace(location, 6, "\\plus \\minus");
		location = equation.find("\\minus", location + 8);
	}
	// 아래는 minus 를 처리하는 부분이다. 
	location = equation.find("\\minus");
	while (location != string::npos)
	{
		equation.replace(location, 6, "\\miiii");
		location = location + 6;
		equation.insert(location, "{");

		int count = 0;
		location ++;
		for(;location < equation.length(); location++)
		{
			if(equation[location] == '{' || equation[location] == '(')
				count ++;
			else if(equation[location] == '}' || equation[location] == ')')
				count --;

			if(count == 0)
			{
				if(equation[location] == '\\')
				{
					if(is_operator(location, operator_name))
					{
						if(is_equal_related_operator(operator_name) || operator_name == "comma" || operator_name == "plus")
						{
							equation.insert(location, "}");
							break;
						}
					}
				}
			}
			if(count == -1)
			{
				equation.insert(location, "}");
				break;
			}
			if(location == equation.length() - 1)
			{
				equation.insert(location + 1, "}");
				break;
			}
		}
		location = equation.find("\\minus");
	}

	location = equation.find("\\miiii");
	while (location != string::npos)
	{
		equation.replace(location, 6, " \\minus");
		location = equation.find("\\miiii");
	}
}
void Equation::adjust_subscript()
{
	string::size_type location = 0;
	string operator_name;

	// 연산자가 아닌 Latex 기호들은 중괄호로 감싸버린다 
	while (location < equation.length())
	{
		if(equation[location] == '\\')
		{
			// 연산자가 아닌 경우. 예컨데 \alpha
			if(!is_operator_only_for_subscript(location, operator_name))
			{
				int find = location + operator_name.length() + 1;
				equation.insert(find, "}");
				equation.insert(location, "{");
				location = location + operator_name.length();
			}
		}
		location ++;
	}

	bool end_search = false;
	int loc = 0, find = 0;
	while (!end_search)
	{
		loc = 0; find = 0;
		int max_deep = 0, deep = 0; // 가장 깊은 곳에 위치한 첨자 기호
		int found = -1;
		if(equation[loc] == '_' && loc == 0)
		{
			is_normalized = false;
			end_search = true;
			break;
		}

		while (loc < static_cast<int>(equation.length()))
		{
			if(equation[loc] == '{' || equation[loc] == '(')
				deep ++;
			else if(equation[loc] == '}' || equation[loc] == ')')
				deep --;

			if(deep >= max_deep && equation[loc] == '_')
			{
				found = loc;
				max_deep = deep;
			}
			loc ++;
		}

		if(found == -1)
		{
			end_search = true;
			break;
		}

		loc = found;
		// 첨자 관련 처리시 이 데이터가 시작하는 부분과 끝나는 부분
		int subscript_data_start, subscript_data_end;

		string subscript; // 첨자 데이터
		string base; // 무엇의 첨자인지.
		find = loc;
		find ++;

		while (find < static_cast<int>(equation.length()))
		{
			if(equation[find] != ' ')
				break;

			find ++;
		}

		if(find == equation.length())
		{
			equation.erase(loc, 1); // _ 를 지워버린다.
			continue;
		}

		if(equation[find] == '{' || equation[find] == '(')
		{
			int end_parenth = find_match_parenth(find);
			subscript = equation.substr(find + 1, end_parenth - find - 1);
			remove_braket_parenth(subscript);
			subscript_data_end = end_parenth;
		}
		else if(equation[find] == '\\')
		{
			// 중괄호로 쳐져 있지 않는 것이라는 뜻은 종전에 인식되지 않았던
			// 기호라는 의미이다. 따라서 하나로 처리한다. 
			get_symbol_name(find, operator_name);
			subscript = operator_name;
			remove_braket_parenth(subscript);
			subscript_data_end = find + operator_name.length();
		}
		else
		{
			// 만일 중괄호로 쳐져 있지 않았다면 그냥 괄호 뒤에 한 문자.
			// 참고로 만일 a_\alpha 로 되있었어도 이미 위에서 중괄호 처리를 통해
			// a_{\alpha} 가 되어서 상관이 없다.
			subscript.push_back(equation[find]);
			subscript_data_end = find;
		}

		find = loc;
		find --;

		while (find >= 0)
		{
			if(equation[find] != ' ')
				break;

			find --;
		}

		// 앞에 첨자가 없을 경우
		if(find == -1)
		{
			base = "";
			subscript_data_start = 0;
		}

		else if(equation[find] == '}' || equation[find] == ')')
		{
			// 이 경우 중괄호 속에 들어 있는 것이 바로 피연산자가 되겠다.
			int start_parenth = find_match_parenth(find);
			base = equation.substr(start_parenth + 1, find - start_parenth - 1);
			remove_braket_parenth(base);
			subscript_data_start = start_parenth;
		}
		else
		{
			int original_location = find;
			for(;find >= 0; find --)
			{		
				if(equation[find] == '\\')
				{
					equation.insert(find, "{");
					equation.insert(loc + 1, "}");
					subscript_data_end += 2;
					subscript_data_start = find;
					base = equation.substr(subscript_data_start + 1, loc - subscript_data_start);
					remove_braket_parenth(base);
					break;
				}
				else if(find == 0)
				{
					base.push_back(equation[original_location]);
					subscript_data_start = original_location;
					break;
				}
				else if(is_alpha(equation[find]))
				{
					continue;
				}
				else
				{
					base.push_back(equation[original_location]);
					subscript_data_start = original_location;
					break;
				}

			}
		}
		// \_ 로 하는 것은 어떤 첨자를 처리했는지 구분하기 위함. 
		string what_to_replace = "{\\" + base + "-" + subscript + "} ";
		equation.replace(subscript_data_start, subscript_data_end - subscript_data_start + 1, what_to_replace);

		for(int i = 0; i < static_cast<int>(base.size()); i ++)
		{
			if(base[i] == '-')
			{
				base.replace(i, 1, "_");
				continue;
			}
		}

		for(int i = 0; i < static_cast<int>(subscript.size()); i ++)
		{
			if(subscript[i] == '-')
			{
				subscript.replace(i, 1, "_");
				continue;
			}
		}
		non_operator_list.push_back(base + "_" + subscript);
		if(is_keyword_operand(base))
			operand_as_keyword.push_back(base + "_" + subscript);

	}
	find = 0;
	while (find < static_cast<int>(equation.length()))
	{
		if(equation[find] == '-')
		{
			equation.replace(find, 1, "_");
		}
		find ++;
	}

	// 다시 묶어 버린다. 첨자로 치환된 것을 묶기 위해!
	location = 0;
	while (location < equation.length())
	{
		if(equation[location] == '\\')
		{
			// 연산자가 아닌 경우. 예컨데 \alpha, \a_1 등등
			if(!is_operator(location, operator_name))
			{
				int find = location + operator_name.length() + 1;
				equation.insert(find, "}");
				equation.insert(location, "{");
				location = location + operator_name.length();
			}
		}
		location ++;
	}

}
void Equation::adjust_dots()
{
	// 먼저 연속된 ... 들이 있는지 확인한다.
	bool consecutive_dots_enable = false;
	int dots_begin = 0;
	for(int i = 0; i < static_cast<int>(equation.length()); i++)
	{
		if(!consecutive_dots_enable && equation[i] == '.')
		{
			consecutive_dots_enable = true;
			dots_begin = i;
			continue;
		}
		else if(consecutive_dots_enable && equation[i] == '.')
			continue;

		if(consecutive_dots_enable && equation[i] != '.')
		{
			consecutive_dots_enable = false;

			if(i - dots_begin == 1)
			{
				continue;
			}

			equation.erase(dots_begin, i - dots_begin);
			equation.insert(dots_begin, " \\cdots ");
			i = -1;
			continue;
		}
	}

	// 그럼 이제 2 개 이상의 연속한 . 들은 모두 
	// \cdots 로 치환되버렸다. 

	string operator_name;

	// 먼저 소수점으로 사용되지 않는 . 을 제거한다. 
	for(string::size_type location = 0; location < equation.length(); location++)
	{
		if(equation[location] == '.')
		{
			int find = location - 1;
			while (find >= 0)
			{
				if(equation[find] == ' ')
				{
					find --;
					continue;
				}
				else if(is_digit(equation[find]))
					break;
				else if(find == 0 || !is_digit(equation[find]))
				{
					find = location + 1;
					while (find < static_cast<int>(equation.length()))
					{
						if(equation[find] == ' ')
						{
							find ++;
							continue;
						}
						else if(is_digit(equation[find]))
							break;
						else if(find == equation.length() - 1 || !is_digit(equation[find]))
						{
							equation.erase(location, 1);
							location --;
							break;
						}
					}

					break;
				}
			}
		}
	}

	// 그 다음에 cdots 등을 처리
	int j;
	for(int i = 0; i < static_cast<int>(equation.length()); i ++)
	{
		if(equation[i] == '\\')
		{
			get_symbol_name(i, operator_name);
			if(is_dot(operator_name))
			{
				string operator_process;

				int end = i + operator_name.length();
				int begin = i - 1;

				int from = -1, to = -1; // 한 쪽이 설정되지 않을 때 -1 로 확인
				bool inside_dots = false;

				// 오른쪽으로 가는 부분.
				for(j = end + 1; j < static_cast<int>(equation.length()); j ++)
				{
					if(equation[j] == ' ')
						continue;
					if(equation[j] == '\\')
					{
						if(is_operator(j, operator_name))
						{
							if(is_two_parameter_operator(operator_name))
							{
								inside_dots = true;
								to = j + operator_name.length();

								operator_process = operator_name;
								break;
							}
						}
					}
					else
						break;
				}

				// 왼쪽으로 가는 부분
				for(j = begin; j >= 0; j --)
				{
					if(equation[j] == ' ')
						continue;
					else break;
				}
				for(; j >= 0; j --)
				{
					if(is_alpha(equation[j]))
						continue;
					else if(equation[j] == '\\')
					{
						if(is_operator(j, operator_name))
						{
							if(is_two_parameter_operator(operator_name))
							{
								inside_dots = true;
								from = j; 

								operator_process = operator_name;
								break;
							}
						}
					}
					else
						break;
				}

				// 점들이 있는 부분에 연산자가 있을 경우
				if(inside_dots)
				{
					if(from == -1)
					{
						from = begin + 1;
					}
					else if(to == -1)
					{
						to = end;
					}

					equation.erase(from, to - from + 1);
					equation.insert(from, "\\" + operator_name);

					i = -1;
					continue;
				}
				else
				{
					equation.erase(begin + 1, end - begin);

					i = -1;
					continue;
				}
			}
		}
	}
}
void Equation::adjust_braket()
{
	// 먼저 \sqrt[] 형태를 처리한다. 
	int location = equation.find("\\sqrt");
	while (location != string::npos)
	{
		int sqrt_found = location;
		location = location + 5; //sqrt 옆을 가리킨다. 
		for(;location < static_cast<int>(equation.length()); location ++)
		{
			if(equation[location] == ' ')
				continue;

			// 대괄호를 찾았다!
			else if(equation[location] == '[')
			{
				int end = find_match_parenth(location); // ] 를 찾는다.
				string btw = equation.substr(location + 1, end - location - 1); // 지수를 찾는다. 
				btw = "\\frac{1}{ " + btw + " }"; 

				for(int find= end + 1; find < static_cast<int>(equation.length()); find ++)
				{
					if(equation[find] == ' ')
						continue;
					else if(equation[find] == '{')
					{
						int b_end = find_match_parenth(find); // } 를 찾는다.
						equation.insert(b_end + 1, " \\exponent { " + btw + " }");
						equation.erase(sqrt_found, end - sqrt_found + 1);
						break;
					}
					else
					{
						// sqrt 가 중괄호로 둘러쌓여 있지 않을 때. 즉
						// \sqrt[2]3 과 같은 꼴이면 \sqrt[2]{3} 으로 감싼다. 
						equation.insert(find, "{");
						equation.insert(find + 2, "}"); 

						equation.insert(find + 3, " \\exponent { " + btw + " }" );
						equation.erase(sqrt_found, end - sqrt_found + 1);
						break;
					}
				}
			}
			else
				break;
		}
		location = equation.find("\\sqrt", sqrt_found + 1);
	}
	// 먼저 \| 기호를 찾는다. (norm 기호)
	location = equation.find("\\|"); 
	while (location != equation.npos)
	{
		int end_match = equation.find("\\|", location + 1);
		if(end_match != equation.npos)
		{
			string btw = equation.substr(location + 2, end_match - location - 2);
			equation.erase(location, end_match - location + 2);
			equation.insert(location, "\\norm{ " + btw + "}");
		}
		else
		{
			equation.replace(location, 2, " {\\twobar}");
		}
		location = equation.find("\\|", location);
	}

	// 그 다음 | 기호를 찾는다. (절대값 혹은 나눗셈)
	location = equation.find("|"); 
	while (location != equation.npos)
	{
		int end_match = equation.find("|", location + 1);
		if(end_match != equation.npos)
		{
			string btw = equation.substr(location + 1, end_match - location - 1);
			equation.erase(location, end_match - location + 1);
			equation.insert(location, "\\abs{ " + btw + "}");
		}
		else
		{
			equation.replace(location, 1, " \\div ");
		}
		location = equation.find("|", location);
	}

	// 개구간 폐구간을 처리한다.
	for(location = 0; location < static_cast<int>(equation.length()); location++)
	{
		if(equation[location] == '[')
		{
			int match = find_real_match_parenth(location, equation);
			if(equation[match] == ')')
			{
				equation[match] = '}';
				equation.replace(location, 1, "\\lopenrclose{");
				location = 0;
			}
		}
		else if(equation[location] == ']')
		{
			int match = find_real_match_parenth(location, equation);
			if(equation[match] == '(')
			{
				equation[location] = '}';
				equation.replace(match, 1, "\\lcloseropen{");
			}
		}
	}


	// 이제 [] 를 함수의 형태로 변환한다.
	// Gaussian 으로

	location = equation.find("[");
	while (location != equation.npos)
	{
		int find = location;
		int count = 0;
		bool success = false;
		while (find < static_cast<int>(equation.length()))
		{
			if(equation[find] == '[')
				count ++;
			else if(equation[find] == ']')
				count --;

			if(count == 0 && equation[find] == ']')
			{
				equation.replace(location, 1, "{");
				equation.replace(find, 1, "}");
				equation.insert(location, "\\gaussian");
				success = true;
				break;
			}
			find ++;
		}

		if(!success)
		{
			is_normalized = false;
			return;
		}
		location = equation.find("[");
	}

}
void Equation::is_syntax_correct()
{
	int count = 0;
	for(int i = 0; i < static_cast<int>(equation.length()); i ++)
	{
		if(equation[i] == '{' ||  equation[i] == '(' || equation[i] == '[') 
			count ++;
		else if(equation[i] == '}' || equation[i] == ')' || equation[i] == ']')
			count --;
		if(count < 0)
		{
			is_normalized = false;
			return;
		}
	}
	if(count != 0)
		is_normalized = false;

	// 조금 저 정밀한 검사를 수행한다.
	else
	{
		for(int i = 0; i < static_cast<int>(equation.length()); i ++)
		{
			if(equation[i] == '{') 
			{
				int match = find_match_parenth(i);
				if(equation[match] != '}')
				{
					is_normalized = false;
					return;
				}
			}
			else if(equation[i] == '}')
			{
				int match = find_match_parenth(i);
				if(equation[match] != '{')
				{
					is_normalized = false;
					return;
				}
			}
		}
	}
}
void Equation::adjust_latex()
{
	string operator_name;
	for(int i = 0; i < static_cast<int>(equation.length()); i++)
	{
		if(equation[i] == '\\')
		{
			get_symbol_name(i, operator_name);
			if(operator_name == "label" || operator_name == "begin" || operator_name == "end" || operator_name == "ref")
			{
				int find = i + operator_name.length() + 1;
				for(; find < static_cast<int>(equation.length()); find ++)
				{
					if(equation[find] == ' ')
						continue;
					break;
				}
				if(equation[find] != '{')
				{
					is_normalized  = false;
					return;
				}
				else
				{
					int match = find_match_parenth(find);
					equation.erase(i, match - i + 1);
				}
				i --;
			}
		}
	}

	// 이제 \text 안에 들어가 있는 것을 처리
	for(int i = 0; i < static_cast<int>(equation.length()); i++)
	{
		if(equation[i] == '\\')
		{
			get_symbol_name(i, operator_name);
			if(operator_name == "text")
			{
				int find = i + operator_name.length() + 1;
				int end = 0;
				string text;

				for(; find < static_cast<int>(equation.length()); find ++)
				{
					if(equation[find] == ' ')
						continue;
					break;
				}

				if(equation[find] == '{')
				{
					int match = find_match_parenth(find);
					if(match == -1)
					{
						is_normalized = false;
						return;
					}
					text = equation.substr(find + 1, match - find - 1);
					remove_braket_parenth(text);

					if(text.length() != 0)
					{
						non_operator_list.push_back(text);
						text.insert(0, "\\");
					}

					end = match;
				}
				else if(find == equation.length())
				{
					is_normalized = false;
					return;
				}
				else
				{
					text = equation.substr(find + 1, 1);
					text.insert(0, "\\");
					non_operator_list.push_back(text);

					end = find + 1;
				}
				equation.erase(i, end - i + 1);

				if(text.length() != 0)
					equation.insert(i, " {" + text + " }");
			}
		}
	}


	int location = equation.find("\\\\");
	while (location != equation.npos)
	{
		equation.replace(location, 2, "");
		location = equation.find("\\\\");
	}
}